<?php
// 应用公共文件

const ORDER_WAIT = 0;           //待支付
const ORDER_SUC = 1;            //支付成功
const ORDER_REFUND = 2;         //退款成功
const ORDER_REFUNDING = -1;      //退款中，应尽量保证无该状态
const ORDER_EXPIRE = -2;         //退款接口返回失败的订单状态

/**
 * 统一API返回格式
 * @param int $code 状态码
 * @param mixed $data 返回数据
 * @param string $message 返回消息
 * @return \think\response\Json
 */
if (!function_exists('apiReturnData')) {
    function apiReturnData(int $code = 1, $data = [], string $message = 'ok')
    {
        $result = [
            'code' => $code,
            'message' => $message,
            'result' => $data,
            'timestamp' => time(),
        ];

        // 添加请求追踪ID（如果存在）
        if ($traceId = request()->header('X-Trace-Id')) {
            $result['trace_id'] = $traceId;
        }

        return json($result);
    }
}

/**
 * 通用API返回格式（兼容旧版本）
 * @param int $code 状态码
 * @param mixed $result 返回数据
 * @param string $message 返回消息
 * @return \think\response\Json
 */
if (!function_exists('commonApiReturn')) {
    function commonApiReturn(int $code = 1, $result = [], string $message = 'ok')
    {
        return apiReturnData($code, $result, $message);
    }
}

/**
 * 数组转对象
 * @param array $arr 数组
 * @return object|false
 */
function arrayToObject($arr = [])
{
    if (gettype($arr) != 'array') {
        return false;
    }
    foreach ($arr as $k => $v) {
        if (gettype($v) == 'array' || getType($v) == 'object') {
            $arr[$k] = (object)arrayToObject($v);
        }
    }
    return (object)$arr;
}

/**
 * 生成随机字符串
 * @param int $length 长度
 * @param string $type 类型：number|letter|string|all
 * @param int $convert 是否转换大小写
 * @return string
 */
if (!function_exists('randomStr')) {
    function randomStr(int $length = 6, string $type = 'string', int $convert = 0): string
    {
        $config = [
            'number' => '1234567890',
            'letter' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
            'string' => 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789',
            'all' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
        ];

        if (!isset($config[$type])) {
            $type = 'string';
        }
        
        $string = $config[$type];
        $result = substr(str_shuffle(str_repeat($string, rand(5, 8))), 0, $length);
        
        return $convert ? strtoupper($result) : $result;
    }
}

/**
 * 记录日志（优化版本 - 支持数组显示）
 * @param string $msg 日志消息
 * @param array $data 日志数据
 * @param string $type 日志类型
 */
if (!function_exists('logs')) {
    function logs(string $msg = '', array $data = [], string $type = 'info'): void
    {
        $context = [
            'data' => $data,
            'url' => request()->url(true),
            'method' => request()->method(),
            'ip' => request()->ip(),
            'user_agent' => request()->header('User-Agent'),
            'timestamp' => date('Y-m-d H:i:s'),
        ];

        // 将数组转换为JSON字符串，便于查看
        $contextJson = json_encode($context, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        $fullMessage = $msg . ' | Context: ' . $contextJson;

        \think\facade\Log::$type($fullMessage);
    }
}

/**
 * 增强的日志记录函数
 * @param string $message 日志消息
 * @param array $context 上下文数据
 * @param string $level 日志级别
 */
if (!function_exists('logWithContext')) {
    function logWithContext(string $message, array $context = [], string $level = 'info'): void
    {
        // 格式化上下文数据
        $formattedContext = [];
        foreach ($context as $key => $value) {
            if (is_array($value) || is_object($value)) {
                $formattedContext[$key] = json_encode($value, JSON_UNESCAPED_UNICODE);
            } else {
                $formattedContext[$key] = $value;
            }
        }

        // 构建完整的日志消息
        $contextString = '';
        if (!empty($formattedContext)) {
            $contextParts = [];
            foreach ($formattedContext as $key => $value) {
                $contextParts[] = "{$key}={$value}";
            }
            $contextString = ' [' . implode(', ', $contextParts) . ']';
        }

        $fullMessage = $message . $contextString;
        \think\facade\Log::$level($fullMessage);
    }
}

/**
 * 结构化日志记录
 * @param string $message 日志消息
 * @param array $data 数据
 * @param string $level 日志级别
 */
if (!function_exists('structuredLog')) {
    function structuredLog(string $message, array $data = [], string $level = 'info'): void
    {
        $logData = [
            'message' => $message,
            'timestamp' => date('Y-m-d H:i:s'),
            'request_id' => uniqid('req_', true),
            'data' => $data
        ];

        $jsonLog = json_encode($logData, JSON_UNESCAPED_UNICODE);
        \think\facade\Log::$level($jsonLog);
    }
}

/**
 * 生成唯一ID
 * @param string $prefix 前缀
 * @return string
 */
if (!function_exists('generateUniqueId')) {
    function generateUniqueId(string $prefix = ''): string
    {
        return $prefix . date('YmdHis') . mt_rand(1000, 9999);
    }
}

/**
 * 格式化文件大小
 * @param int $bytes 字节数
 * @param int $precision 精度
 * @return string
 */
if (!function_exists('formatFileSize')) {
    function formatFileSize(int $bytes, int $precision = 2): string
    {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        
        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }
        
        return round($bytes, $precision) . ' ' . $units[$i];
    }
}

/**
 * 验证身份证号
 * @param string $idCard 身份证号
 * @return bool
 */
if (!function_exists('validateIdCard')) {
    function validateIdCard(string $idCard): bool
    {
        if (strlen($idCard) !== 18) {
            return false;
        }
        
        // 验证格式
        if (!preg_match('/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/', $idCard)) {
            return false;
        }
        
        // 验证校验码
        $weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
        $checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
        
        $sum = 0;
        for ($i = 0; $i < 17; $i++) {
            $sum += intval($idCard[$i]) * $weights[$i];
        }
        
        $checkCode = $checkCodes[$sum % 11];
        return strtoupper($idCard[17]) === $checkCode;
    }
}

/**
 * 脱敏处理
 * @param string $string 原始字符串
 * @param int $start 开始位置
 * @param int $end 结束位置
 * @param string $mask 掩码字符
 * @return string
 */
if (!function_exists('maskString')) {
    function maskString(string $string, int $start = 3, int $end = 4, string $mask = '*'): string
    {
        $length = mb_strlen($string, 'UTF-8');
        
        if ($length <= $start + $end) {
            return str_repeat($mask, $length);
        }
        
        $prefix = mb_substr($string, 0, $start, 'UTF-8');
        $suffix = mb_substr($string, -$end, $end, 'UTF-8');
        $maskLength = $length - $start - $end;
        
        return $prefix . str_repeat($mask, $maskLength) . $suffix;
    }
}

/**
 * 检查是否为手机号
 * @param string $mobile 手机号
 * @return bool
 */
if (!function_exists('isMobile')) {
    function isMobile(string $mobile): bool
    {
        return preg_match('/^1[3-9]\d{9}$/', $mobile);
    }
}

/**
 * 检查是否为邮箱
 * @param string $email 邮箱
 * @return bool
 */
if (!function_exists('isEmail')) {
    function isEmail(string $email): bool
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }
}

/**
 * 获取客户端IP
 * @return string
 */
if (!function_exists('getClientIp')) {
    function getClientIp(): string
    {
        return request()->ip();
    }
}

/**
 * 安全的JSON编码
 * @param mixed $data 数据
 * @param int $options JSON选项
 * @return string
 */
if (!function_exists('safeJsonEncode')) {
    function safeJsonEncode($data, int $options = JSON_UNESCAPED_UNICODE): string
    {
        $json = json_encode($data, $options);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new \InvalidArgumentException('JSON编码失败: ' . json_last_error_msg());
        }
        
        return $json;
    }
}

/**
 * 安全的JSON解码
 * @param string $json JSON字符串
 * @param bool $assoc 是否返回关联数组
 * @return mixed
 */
if (!function_exists('safeJsonDecode')) {
    function safeJsonDecode(string $json, bool $assoc = true)
    {
        $data = json_decode($json, $assoc);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new \InvalidArgumentException('JSON解码失败: ' . json_last_error_msg());
        }
        
        return $data;
    }
}

function curl_http($url, $isPostRequest = false, $data = [], $header = [], $certParam = [])
{
    $curlObj = curl_init(); // 启动一个CURL会话
    //如果是POST请求
    if ($isPostRequest) {
        if (is_array($data) || is_object($data)) {
            $data = http_build_query($data);
        }
        curl_setopt($curlObj, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curlObj, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
    } else {  //get请求检查是否拼接了参数，如果没有，检查$data是否有参数，有参数就进行拼接操作
        $getParamStr = '';
        if (!empty($data) && is_array($data)) {
            $tmpArr = [];
            foreach ($data as $k => $v) {
                $tmpArr[] = $k . '=' . $v;
            }
            $getParamStr = implode('&', $tmpArr);
        }
        //检查链接中是否有参数
        $url .= strpos($url, '?') !== false ? '&' . $getParamStr : '?' . $getParamStr;
    }
    curl_setopt($curlObj, CURLOPT_URL, $url); // 要访问的地址
    //检查链接是否https请求
    if (strpos($url, 'https') !== false) {
        //设置证书
        if (!empty($certParam) && isset($certParam['cert_path']) && isset($certParam['key_path'])) {
            curl_setopt($curlObj, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
            curl_setopt($curlObj, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
            //设置证书
            //使用证书：cert 与 key 分别属于两个.pem文件
            curl_setopt($curlObj, CURLOPT_SSLCERTTYPE, 'PEM');
            curl_setopt($curlObj, CURLOPT_SSLCERT, $certParam['cert_path']);
            curl_setopt($curlObj, CURLOPT_SSLKEYTYPE, 'PEM');
            curl_setopt($curlObj, CURLOPT_SSLKEY, $certParam['key_path']);
        } else {
            curl_setopt($curlObj, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
            curl_setopt($curlObj, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在
        }
    }
    // 模拟用户使用的浏览器
    if (isset($_SERVER['HTTP_USER_AGENT'])) {
        curl_setopt($curlObj, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
    }
    curl_setopt($curlObj, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
    curl_setopt($curlObj, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
    curl_setopt($curlObj, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
    curl_setopt($curlObj, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
    curl_setopt($curlObj, CURLOPT_HTTPHEADER, $header);   //设置头部
    curl_setopt($curlObj, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
    $result = curl_exec($curlObj); // 执行操作
    if (curl_errno($curlObj)) {
        $result = 'error: ' . curl_error($curlObj);//捕抓异常
    }
    curl_close($curlObj); // 关闭CURL会话
    if (!xml_parser($result)) {
        return json_decode($result, true);  // 返回数据，json格式
    } else {
        return $result;  //XML
    }
}


/**
 * 自定义xml验证函数
 * @param $str
 * @return bool|mixed
 * @author yangliang
 * @date 2020/12/15 17:21
 */
function xml_parser($str)
{
    $xml_parser = xml_parser_create();
    if (!xml_parse($xml_parser, $str, true)) {
        xml_parser_free($xml_parser);
        return false;
    } else {
        return (json_decode(json_encode(simplexml_load_string($str)), true));
    }
}

/**生成唯一订单号**/
function orderNo()
{
    return date('YmdHi') . substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}